#pragma once
#include <iostream>
#include <functional>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Protocol.hpp"

using namespace socket_ns;
using namespace log_ns;

using process_t = std::function<std::shared_ptr<Response>(std::shared_ptr<Request>)>;

class IOService
{
public:
    IOService(process_t process) :_process(process)
    {
    }
    void IOExcute(SockSPtr sock, InetAddr &addr)
    {
        std::string packagestreamqueue; // 写在while循环外，存储信息
        while (true)
        {
            // 1.负责读取
            ssize_t n = sock->Recv(&packagestreamqueue);
            if(n <= 0)
            {
                LOG(INFO, "client %s quit or recv error\n", addr.AddrStr().c_str());
                break;
            }

            std::cout << "--------------------------------------------" << std::endl;
            std::cout << "packagestreamqueue: \n" << packagestreamqueue << std::endl;

            // 我们能保证读到的是完整的报文？ 不能！
            // 2.报文解析，提取报头和有效载荷
            std::string package = Decode(packagestreamqueue);
            if(package.empty()) continue;
            // 我们能保证读到的是一个完整的报文！！！
            auto req = Factory::BuildRequestDefault();
            std::cout << "package: \n" << package << std::endl;

            // 3.反序列化
            req->Deserialize(package); // 反序列化 将字符串转成结构化

            // 4.业务处理
            auto resp = _process(req); // 业务处理(通过请求，得到应答)

            // 5.序列化应答
            std::string respjson;
            resp->Serialize(&respjson); // 序列化
            std::cout << "respjson: \n" << respjson << std::endl;

            // 6.添加len长度
            respjson = Encode(respjson);
            std::cout << "respjson add header done: \n" << respjson << std::endl;

            // 7.发送回去
            sock->Send(respjson);
        }
    }
    // 测试
    // void IOExcute(SockSPtr sock, InetAddr &addr)
    // {
    //     while (true)
    //     {
    //         std::string message;
    //         ssize_t n = sock->Recv(&message);
    //         if(n > 0)
    //         {
    //             LOG(INFO, "get message from client [%s],message: %s\n", addr.AddrStr().c_str(), message.c_str());
    //             std::string hello = "hello";

    //             sock->Send(hello);
    //         }
    //         else if(n == 0)
    //         {
    //             LOG(INFO, "client %s quit\n", addr.AddrStr().c_str());
    //             break;
    //         }
    //         else 
    //         {
    //             LOG(ERROR, "read error\n", addr.AddrStr().c_str());
    //             break;
    //         }
    //     }
    // }
    ~IOService()
    {
    }
private:
    process_t _process;
};